﻿using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.Linq;
using System.Reflection;

namespace CodeCamp.BL.Helpers
{
	public static class EntityFrameworkExtension
	{
		public static void AttachAsModified(this ObjectContext context, IEntityWithKey entity)
		{
			context.Attach(entity);
			SetAllPropertiesModified(context, entity);
		}

		public static void AttachAsModifiedTo(this ObjectContext context, string entitySetName, object entity)
		{
			context.AttachTo(entitySetName, entity);
			SetAllPropertiesModified(context, entity);
		}

		private static void SetAllPropertiesModified(ObjectContext context, object entity)
		{
			ObjectStateEntry stateEntry = context.ObjectStateManager.GetObjectStateEntry(entity);
			foreach (string propertyName in stateEntry.CurrentValues.DataRecordInfo.FieldMetadata.Select(f => f.FieldType.Name))
			{
				stateEntry.SetModifiedProperty(propertyName);
			}
		}



		/// <summary>
		/// Copies the values of the public properties of one class to another
		/// </summary>
		/// <typeparam name="TSource">The type of the source.</typeparam>
		/// <typeparam name="TDest">The type of the dest.</typeparam>
		/// <param name="dst">The Destination object</param>
		/// <param name="src">The Source object</param>
		/// <returns>the destination object</returns>
		public static TDest UpdateSimpleValues<TSource, TDest>(this TDest dst, TSource src, string exclude)
		{
			PropertyInfo[] sourcePropertyInfos = typeof(TSource).GetProperties();
			PropertyInfo[] destinationPropertyInfos = typeof(TDest).GetProperties();

			foreach (PropertyInfo sourcePInfo in sourcePropertyInfos.Where(p => p.CanRead))
			{
				PropertyInfo destPInfo = destinationPropertyInfos.FirstOrDefault(
					p => p.Name == sourcePInfo.Name
						&& p.Name != exclude
						&& p.PropertyType == sourcePInfo.PropertyType
						&& p.CanWrite
						&& p.PropertyType.Module.Name != "System.Data.Entity.dll");

				if (destPInfo != null)
					destPInfo.SetValue(dst, sourcePInfo.GetValue(src, null), null);
			}

			return dst;
		}
	}


}
